package com.zzzy.sys.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zzzy.common.exception.WarningException;
import com.zzzy.common.util.AssertUtil;
import com.zzzy.common.util.CglibBeanCopierUtil;
import com.zzzy.common.util.MyBatisUtils;
import com.zzzy.common.vo.PageResult;
import com.zzzy.framework.common.constant.AdminUserConstant;
import com.zzzy.framework.common.dict.DictService;
import com.zzzy.framework.common.enums.sys.UserStatusEnum;
import com.zzzy.framework.common.util.SecurityUtils;
import com.zzzy.sys.cache.LoginErrorCountCache;
import com.zzzy.sys.common.enums.GenderEnum;
import com.zzzy.sys.dao.entity.Dept;
import com.zzzy.sys.dao.entity.Role;
import com.zzzy.sys.dao.entity.User;
import com.zzzy.sys.dao.entity.UserRole;
import com.zzzy.sys.vo.usermanage.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserManageService extends UserService {

    private static final String INIT_PASSWORD = "111111";

    @Resource
    private DeptService deptService;
    @Resource
    private UserRoleService userRoleService;
    @Resource
    private RoleService roleService;
    @Resource
    private DictService dictService;
    @Resource
    private LoginErrorCountCache loginErrorCountCache;

    @Transactional
    public void add(UserAddReq userAddReq) {
        User existsUser = getUserByUsername(userAddReq.getUsername());
        AssertUtil.isNull(existsUser, "用户登录名已存在");
        if (Objects.nonNull(userAddReq.getDeptId())){
            Dept dept = deptService.getById(userAddReq.getDeptId());
            AssertUtil.nonNull(dept, "部门不存在");
        }

        User user = CglibBeanCopierUtil.copy(userAddReq, User.class);
        user.setCreateTime(LocalDateTime.now());
        user.setPassword(SecurityUtils.encryptPassword(INIT_PASSWORD));
        user.setStatus(UserStatusEnum.CREATE.getValue());
        baseMapper.insert(user);

        operateRole(user.getId(), userAddReq.getRoleIds());
    }

    public PageResult<User> getUserPage(UserPageReq queryReq) {
        IPage<User> mpPage = MyBatisUtils.buildPage(queryReq);
        mpPage = baseMapper.selectUserPage(mpPage, queryReq);
        return new PageResult<>(mpPage);
    }

    @Transactional
    public void updateById(UserUpdateReq updateReq) {
        AssertUtil.isNotEquals(AdminUserConstant.ID, updateReq.getId(), "超级管理员不能修改");
        User existsUser = getUserByUsername(updateReq.getUsername());
        AssertUtil.isTrue(Objects.isNull(existsUser) || updateReq.getId().equals(existsUser.getId()), "用户登录名已存在");
        if (Objects.nonNull(updateReq.getDeptId())){
            Dept dept = deptService.getById(updateReq.getDeptId());
            AssertUtil.nonNull(dept, "部门不存在");
        }
        User user = getUserById(updateReq.getId());
        CglibBeanCopierUtil.copy(updateReq, user);
        user.setUpdateTime(LocalDateTime.now());
        updateById(user);
        //修改用户角色
        operateRole(user.getId(), updateReq.getRoleIds());
    }

    public void deleteById(Long id) {
        AssertUtil.isNotEquals(AdminUserConstant.ID, id, "超级管理员不能删除");
        User user = getUserById(id);
        AssertUtil.isEquals(UserStatusEnum.CREATE.getValue(), user.getStatus(), "只有新建状态用户可删除,其他状态用户请选择暂停或离职");
        baseMapper.deleteById(id);
    }

    public void resetPwd(Long id) {
        User user = getUserById(id);
        user.setPassword(SecurityUtils.encryptPassword(INIT_PASSWORD));
        user.setUpdateTime(LocalDateTime.now());
        updateById(user);
    }

    public void operateRole(Long userId, List<Long> roleIdList) {
        AssertUtil.isNotEquals(AdminUserConstant.ID, userId, "超级管理员不能操作");
        userRoleService.remove(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, userId));
        if (!CollectionUtils.isEmpty(roleIdList)) {
            userRoleService.saveBatch(roleIdList.stream().map(roleId -> {
                UserRole userRole = new UserRole();
                userRole.setRoleId(roleId);
                userRole.setUserId(userId);
                return userRole;
            }).collect(Collectors.toList()));
        }
    }

    public UserUpdateInfoRes getUserUpdateInfoResById(Long id) {
        User user = getSimpleUserById(id);
        UserUpdateInfoRes userUpdateInfoRes = CglibBeanCopierUtil.copy(user, UserUpdateInfoRes.class);
        List<Role> roleList = roleService.getRoleListByUserId(id);
        userUpdateInfoRes.setRoleIds(roleList.stream().map(Role::getId).collect(Collectors.toList()));
        return userUpdateInfoRes;
    }

    /**
     * excel导入用户数据
     */
    @Transactional
    public UserImportExcelRes importUserList(List<UserImportExcelVO> userImportList, Boolean updateSupport) {
        validateForImport(userImportList);
        UserImportExcelRes importRes = UserImportExcelRes.builder().createUsernames(new ArrayList<>())
                .updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build();
        for (UserImportExcelVO userImportVO : userImportList){
            String errorMessage = getValidateUserMessageForImport(userImportVO, updateSupport);
            if (StringUtils.isNotBlank(errorMessage)){
                importRes.getFailureUsernames().put(userImportVO.getUsername(), errorMessage);
                continue;
            }
            User userByUsername = getUserByUsername(userImportVO.getUsername());
            if (Objects.isNull(userByUsername)){
                addForImport(userImportVO);
                importRes.getCreateUsernames().add(userImportVO.getUsername());
                continue;
            }
            if (updateSupport){
                updateForImport(userImportVO);
                importRes.getUpdateUsernames().add(userImportVO.getUsername());
            }
        }
        return importRes;
    }

    private void updateForImport(UserImportExcelVO userImportVO) {
        User user = getUserByUsername(userImportVO.getUsername());
        CglibBeanCopierUtil.copy(userImportVO, user);
        user.setUpdateTime(LocalDateTime.now());
        Dept dept = deptService.getDeptByName(userImportVO.getDeptName());
        if (Objects.nonNull(dept)){
            user.setDeptId(dept.getId());
        }
        baseMapper.updateById(user);
    }

    private void addForImport(UserImportExcelVO userImportVO) {
        User user = CglibBeanCopierUtil.copy(userImportVO, User.class);
        user.setCreateTime(LocalDateTime.now());
        user.setPassword(SecurityUtils.encryptPassword(INIT_PASSWORD));
        Dept dept = deptService.getDeptByName(userImportVO.getDeptName());
        if (Objects.nonNull(dept)){
            user.setDeptId(dept.getId());
        }
        baseMapper.insert(user);
    }

    private void validateForImport(List<UserImportExcelVO> userImportList) {
        AssertUtil.isNotEmpty(userImportList, "导入用户数据不能为空");
        long count = userImportList.stream().filter(user -> StringUtils.isNotBlank(user.getUsername())).count();
        AssertUtil.isTrue(userImportList.size() == count, "导入的文件中存在用户名为空的数据");
        Map<String, Long> usernameCounts = userImportList.stream()
                .collect(Collectors.groupingBy(UserImportExcelVO::getUsername, Collectors.counting()));
        List<String> duplicateUsernames = usernameCounts.entrySet().stream()
                .filter(entry -> entry.getValue() > 1)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        if (!duplicateUsernames.isEmpty()) {
            String message = duplicateUsernames.stream().collect(Collectors.joining(","));
            throw new WarningException("以下登录名在文件中重复: " + message);
        }
    }

    private String getValidateUserMessageForImport(UserImportExcelVO userImportVO, Boolean updateSupport) {
        User user = getUserByUsername(userImportVO.getUsername());
        if (!updateSupport && Objects.nonNull(user)){
            return "用户登录名已存在";
        }
        String usernameMessage = StringUtils.isBlank(userImportVO.getUsername()) ? "用户登录名不能为空" : "";
        String nicknameMessage = StringUtils.isBlank(userImportVO.getNickName()) ? "用户名称不能为空" : "";
        String genderMessage = dictService.getDictDataMap(GenderEnum.class).get(userImportVO.getSex()) == null ? "性别填写错误" : "";
        String statusMessage = dictService.getDictDataMap(UserStatusEnum.class).get(userImportVO.getStatus()) == null ? "用户状态填写错误" : "";
        String deptMessage = Objects.isNull(deptService.getDeptByName(userImportVO.getDeptName())) ? "部门名称不存在" : "";
        return Arrays.asList(usernameMessage, nicknameMessage, genderMessage, statusMessage, deptMessage)
                .stream().filter(StringUtils::isNotBlank).collect(Collectors.joining(","));
    }

    /**
     * 用户解锁
     */
    public void unlock(Long id) {
        User user = getUserById(id);
        loginErrorCountCache.removeCache(user.getUsername());
    }
}
